package cn.zz.comm.util;

import cn.hutool.core.date.DatePattern;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @author zhongq
 * @since 2022/3/12
 */
public class DateTimeUtil {

	public static final int SEC_PER_DAY = 86400;
	public static final ZoneId ZID_GMT = ZoneId.of("GMT");
	public static final ZoneId ZID_PRC = ZoneId.of("PRC");
	/**
	 * 标准日期时间正则，每个字段支持单个数字或2个数字，包括：
	 * 
	 * <pre>
	 *     yyyy-MM-dd HH:mm:ss.SSSSSS
	 *     yyyy-MM-dd HH:mm:ss.SSS
	 *     yyyy-MM-dd HH:mm:ss
	 *     yyyy-MM-dd HH:mm
	 *     yyyy-MM-dd
	 * </pre>
	 */
	public static Pattern REGEX_NORM = Pattern
			.compile("\\d{4}-\\d{1,2}-\\d{1,2}(\\s\\d{1,2}:\\d{1,2}(:\\d{1,2})?)?(" + ".\\d{1,6})?");
	public static String NORM_DATE_PATTERN = "yyyy-MM-dd";
	public static DateTimeFormatter NORM_DATE_FORMAT = DateTimeFormatter.ofPattern(NORM_DATE_PATTERN);
	public static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	public static DateTimeFormatter NORM_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN);
	public static String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
	public static DateTimeFormatter NORM_DATETIME_MS_FORMATTER = DateTimeFormatter.ofPattern(NORM_DATETIME_MS_PATTERN);
	public static String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
	public static DateTimeFormatter ISO8601_FORMATTER = DateTimeFormatter.ofPattern(ISO8601_PATTERN);
	public static String CHINESE_DATE_PATTERN = "yyyy年MM月dd日";
	public static DateTimeFormatter CHINESE_DATE_FORMATTER = DateTimeFormatter.ofPattern(CHINESE_DATE_PATTERN);
	public static String CN_DATE_TIME_PATTERN = "yyyy年MM月dd日HH时mm分ss秒";
	public static DateTimeFormatter CN_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(CN_DATE_TIME_PATTERN);
	public static String PURE_DATE_PATTERN = "yyyyMMdd";
	public static DateTimeFormatter PURE_DATE_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATE_PATTERN);
	public static DateTimeFormatter PURE_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
	public static String PURE_DATETIME_MS_PATTERN = "yyyyMMddHHmmssSSS";
	public static DateTimeFormatter PURE_DATETIME_MS_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATETIME_MS_PATTERN);

	public static long unixTime() {
		return Instant.now().getEpochSecond();
	}

	/**
	 * now plus day's at hour => hour 00:00:00
	 *
	 * @param days
	 *            days after
	 * @param hour
	 *            at hour
	 * @return data
	 */
	public static Date nowAfterDayAtHours(int days, int hour) {
		return Date.from(ZonedDateTime.now().plusDays(days).withHour(hour).withMinute(0).withSecond(0).toInstant());
	}

	/**
	 * 一天的开始 默认 当前日期
	 *
	 * @param days
	 *            前后几天
	 */
	public static long dayStart(int days) {
		return ZonedDateTime.now().plusDays(days).withHour(0).withMinute(0).withSecond(0).toEpochSecond();
	}

	/**
	 * 一天的结束 默认 当前日期
	 *
	 * @param days
	 *            前后几天
	 */
	public static long dayEnd(int days) {
		return dayStart(days + 1) - 1;
	}

	/**
	 * 一个月的开始 0 curr month
	 */
	public static long monthStart(int months) {
		return ZonedDateTime.now().plusMonths(months).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0)
				.toEpochSecond();
	}

	/**
	 * now plus day's hour 00:00:00
	 *
	 * @param days
	 *            days after
	 * @param hour
	 *            hour after
	 * @return data
	 */
	public static Date nowAfterDayHours(int days, int hour) {
		return Date.from(ZonedDateTime.now().plusDays(days).plusHours(hour).withMinute(0).withSecond(0).toInstant());
	}

	/**
	 * now hour after
	 *
	 * @param hour
	 *            hour after
	 * @return data
	 */
	public static Date nowAfterDayHours(int hour) {
		return nowAfter(hour, TimeUnit.HOURS);
	}

	/**
	 * now add hours minutes seconds
	 *
	 * @param hours
	 *            时
	 * @param minutes
	 *            分
	 * @param seconds
	 *            秒
	 * @return date
	 */
	public static Date nowAfter(int hours, int minutes, int seconds) {
		return Date.from(ZonedDateTime.now().plusHours(hours).plusMinutes(minutes).plusSeconds(seconds).toInstant());
	}

	/**
	 * now after date
	 *
	 * @param expire
	 *            时间
	 * @param timeUnit
	 *            时间单位
	 * @return date
	 */
	public static Date nowAfter(long expire, TimeUnit timeUnit) {
		return Date.from(ZonedDateTime.now().plusSeconds(timeUnit.toSeconds(expire)).toInstant());
	}

	public static Date fromUnixTime(long unixTime) {
		return Date.from(zonedDateTime(unixTime).toInstant());
	}

	/**
	 * 格式化
	 */
	public static String nowFormat(DateTimeFormatter formatter) {
		return ZonedDateTime.now().format(formatter);
	}

	public static String format(Date date, String pattern) {
		return "";
	}

	public static String format(Date date, DateTimeFormatter pattern) {
		Objects.requireNonNull(pattern, "date time pattern not null ");
		return "";
	}

	public static Date now() {
		return Date.from(ZonedDateTime.now().toInstant());
	}

	public static ZonedDateTime zonedDateTime(long epochSecond) {
		return Instant.ofEpochSecond(epochSecond).atZone(ZoneId.systemDefault());
	}

	public static String formatDate(ZonedDateTime zonedDateTime) {
		return NORM_DATE_FORMAT.format(zonedDateTime);
	}

	public static String formatDateTime(long epochSecond) {
		return NORM_DATETIME_FORMATTER.format(zonedDateTime(epochSecond));
	}

	public static String formatDate(long epochSecond) {
		return NORM_DATE_FORMAT.format(zonedDateTime(epochSecond));
	}

	public static String format(long epochSecond, DateTimeFormatter formatter) {
		return format(zonedDateTime(epochSecond), formatter);
	}

	public static String formatDateTime(ZonedDateTime zonedDateTime) {
		return format(zonedDateTime, DatePattern.NORM_DATETIME_FORMATTER);
	}

	public static String format(TemporalAccessor time, DateTimeFormatter formatter) {
		return formatter.format(time);
	}

	public static String format(TemporalAccessor time, String pattern) {
		return DateTimeFormatter.ofPattern(pattern).format(time);
	}
}